using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;

using SBPweb.Data;

#if SQL2005
namespace SBPweb.Data.SQL2005
{

	/// <summary>
	/// This class implements a factory wich is able create commands to insert 
	/// entities to the database via stored procedure
	/// </summary>
	/// <typeparam name="T">Entity type</typeparam>
	public class InsertCommandFactory<T>: IInsertFactory<T> where T: Entity
	{

		#region Private fields

		private string mCommandName;
		private string mOutParamName;
		private List<SqlParameterDescriptor> mParams;

		#endregion

		#region Constructor logic

		/// <summary>
		/// Initializes a new InsertCommandFactory instance
		/// </summary>
		/// <param name="storedProcCommandName">Name of the stored procedure</param>
		public InsertCommandFactory(string storedProcCommandName)
			: this(storedProcCommandName, string.Empty)
		{

		}

		/// <summary>
		/// Initializes a new InsertCommandFactory instance
		/// </summary>
		/// <param name="storedProcCommandName">Name of the stored procedure</param>
		/// <param name="outParamName">Name of the out parameter of stored procedure 
		/// (usually the Id of the new entity)</param>
		public InsertCommandFactory(string storedProcCommandName, string outParamName)
            : this(storedProcCommandName, outParamName, null)
		{
		}

		/// <summary>
		/// Initializes a new InsertCommandFactory instance
		/// </summary>
		/// <param name="storedProcCommandName">Name of the stored procedure</param>
		/// <param name="parameters">Input parameters of the stored procedure</param>
		public InsertCommandFactory(string storedProcCommandName, List<SqlParameterDescriptor> parameters)
            : this(storedProcCommandName, string.Empty, parameters)
		{
		}

		/// <summary>
		/// Initializes a new InsertCommandFactory instance
		/// </summary>
		/// <param name="storedProcCommandName">Name of the stored procedure</param>
		/// <param name="outParamName">Name of the out parameter of stored procedure 
		/// (usually the Id of the new entity)</param>
		/// <param name="parameters">Input parameters of the stored procedure</param>
		public InsertCommandFactory(string storedProcCommandName, string outParamName, List<SqlParameterDescriptor> parameters)
		{
			mCommandName = storedProcCommandName;
			mOutParamName = outParamName;
			mParams = parameters;
		}

		#endregion

		#region IInsertFactory<int> Members

		/// <summary>
		/// This method constructs the SqlCommand
		/// </summary>
		/// <param name="db">SqlDatabase db</param>
		/// <param name="entity">T entity to insert</param>
		/// <returns>SqlCommand</returns>
		public SqlCommand ConstructInsertCommand(SqlDatabase db, T entity)
		{
			SqlCommand command = db.GetStoredProcCommand(mCommandName);

			string format = "@{0}";

			if (!string.IsNullOrEmpty(mOutParamName))
			{
				db.AddOutParameter(command, string.Format(format, mOutParamName), SqlDbType.Int, 4);
			}

			if (mParams != null)
			{
				foreach (SqlParameterDescriptor sqlpd in mParams)
				{
                    db.AddInParameter(command, string.Format(format, sqlpd.ParameterName), sqlpd.ParameterType, (sqlpd.Value != null) ? (sqlpd.Value) : (entity.GetValue<object>(sqlpd.FieldName)));
				}
			}

			return command;
		}

		/// <summary>
		/// This method sets the value of the out parameter in the entity
		/// </summary>
		/// <param name="db">SqlDatabase db</param>
		/// <param name="command">SqlCommand command</param>
		/// <param name="entity">T entity</param>
		public void SetNewID(SqlDatabase db, SqlCommand command, T entity)
		{
			if (!string.IsNullOrEmpty(mOutParamName))
			{
				object value = db.GetParameterValue(command, mOutParamName);
				if (value.GetType() == typeof(DBNull))
				{
					value = null;
				}
				int? id = (int?)(value);
				entity.SetValueEx<int?>(mOutParamName, id);
			}
		}

		#endregion

		#region IDbToBusinessEntityNameMapper Members

		/// <summary>
		/// This method maps the parameter name of the stored procedure to entity property name
		/// </summary>
		/// <param name="dbParameter">parameter name</param>
		/// <returns>entity property name</returns>
		public string MapDbParameterToBusinessEntityProperty(string dbParameter)
		{
			return dbParameter;
		}

		#endregion

	}
}
#endif